package com.wei.czz.framework.annex.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.annex.AnnexFormVo;
import com.wei.czz.common.vo.annex.AnnexPreVo;
import com.wei.czz.framework.annex.dao.AnnexPreDao;
import com.wei.czz.framework.annex.entity.AnnexPreEntity;
import com.wei.czz.framework.annex.service.AnnexPreService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-01-18 15:42:18
 * className: AnnexPreServiceImpl
 * version: 1.0
 * description:
 */
@Service("annexPreService")
@AllArgsConstructor
public class AnnexPreServiceImpl extends ServiceImpl<AnnexPreDao, AnnexPreEntity> implements AnnexPreService {

    private static final Logger log = LoggerFactory.getLogger(AnnexPreServiceImpl.class);

    private final RedissonClient redissonClient;

    @Override
    public Long saveAnnex(AnnexPreVo annexPreVo) {

        Long id = annexPreVo.getId();
        AnnexPreEntity annexPre = baseMapper.selectById(id);
        if (Objects.isNull(annexPre)) {
            annexPre = this.buildAnnexPreEntity(annexPreVo, null);
            // 添加
            int count = baseMapper.insert(annexPre);
            log.info("添加附件动态配置前置完成。count={}", count);
        } else {
            if (CommonEnum.ZERO.getValue().equals(annexPre.getStatus())) {
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件配置已启用，无法修改");
            }

            this.buildAnnexPreEntity(annexPreVo, annexPre);
            // 修改
            int count = baseMapper.updateById(annexPre);
            log.info("修改附件动态配置前置完成。count={}", count);
        }
        return id;
    }

    @Override
    public Long copyAnnexPre(Long id) {
        AnnexPreEntity annexPre = baseMapper.selectById(id);
        if (Objects.isNull(annexPre)) {
            log.info("附件动态配置前置不存在。id={}", id);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件配置不存在，请确认");
        }
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        annexPre.setVersion(this.getNextVersion(annexPre.getClassify()))
                .setStatus(CommonEnum.ONE.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                .setCreateTime(date)
                .setCreateUser(userPo.getUsername())
                .setCreateUserId(userPo.getUserId());
        // 添加附件动态配置前置
        int count = baseMapper.insert(annexPre);
        log.info("复制附件动态配置前置完成。count={}", count);
        return annexPre.getId();
    }

    @Override
    public PageDto<AnnexPreEntity> getAnnexPrePageList(AnnexFormVo annexFormVo) {

        Page<AnnexPreEntity> page = new Page<>(annexFormVo.getPage(), annexFormVo.getLimit());

        LambdaQueryWrapper<AnnexPreEntity> annexPreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        annexPreLambdaQueryWrapper.eq(Objects.nonNull(annexFormVo.getClassify()), AnnexPreEntity::getClassify,
                annexFormVo.getClassify())
                .eq(Objects.nonNull(annexFormVo.getStatus()), AnnexPreEntity::getStatus, annexFormVo.getStatus())
                .eq(AnnexPreEntity::getDeleteStatus, annexFormVo.getDeleteStatus());
        // 查询
        baseMapper.selectPage(page, annexPreLambdaQueryWrapper);

        return new PageDto<>(page);
    }

    @Override
    public AnnexPreEntity getAnnexPre(Long id) {
        AnnexPreEntity annexPre = baseMapper.selectById(id);
        if (Objects.isNull(annexPre)) {
            log.info("附件动态配置前置不存在。id={}", id);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件动态配置前置不存在");
        }
        if (CommonEnum.ONE.getValue().equals(annexPre.getDeleteStatus())) {
            log.info("附件动态配置前置已删除。id={}", id);
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "附件动态配置前置已被删除");
        }
        return annexPre;
    }

    @Override
    public AnnexPreEntity getLastAnnexPre(Integer classify) {
        LambdaQueryWrapper<AnnexPreEntity> annexPreLambdaQueryWrapper = new LambdaQueryWrapper<>();
        annexPreLambdaQueryWrapper.eq(AnnexPreEntity::getClassify, classify)
                .eq(AnnexPreEntity::getStatus, CommonEnum.ZERO.getValue())
                .eq(AnnexPreEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<AnnexPreEntity> annexPreList = baseMapper.selectList(annexPreLambdaQueryWrapper);
        log.info("查询附件动态配置前置完成。classify={} isEmpty={}", classify, annexPreList.isEmpty());

        AnnexPreEntity annexPre = annexPreList.stream()
                .max(Comparator.comparing(AnnexPreEntity::getVersion))
                .orElse(null);
        if (Objects.isNull(annexPre)) {
            log.error("附件动态配置前置不存在");
            throw new CzzException("附件配置不存在");
        }
        return annexPre;
    }

    //    @Transactional
    @Override
    public void useAnnexPre(Long id) {
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        /*
            查询分类关联前置主键
         */
//        Set<Long> idSet = baseMapper.selectId(annexUpdateStatusVo.getClassify(), CommonEnum.ZERO.getValue());
//        idSet.remove(annexUpdateStatusVo.getId());

        /*
            启用前置
         */
        AnnexPreEntity annexPre = new AnnexPreEntity();
        annexPre.setId(id)
                .setStatus(CommonEnum.ZERO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getUserId());
        // 更新
        int count = baseMapper.updateById(annexPre);
        log.info("启用附件动态配置前置完成。count={}", count);

//        /*
//            停用正在`启用`中的前置
//         */
//        LambdaUpdateWrapper<AnnexPreEntity> annexPreLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
//        // 设置字段值
//        annexPreLambdaUpdateWrapper.set(AnnexPreEntity::getStatus, CommonEnum.TWO.getValue())
//                .set(AnnexPreEntity::getUpdateTime, date)
//                .set(AnnexPreEntity::getUpdateUser, userPo.getUsername())
//                .set(AnnexPreEntity::getUpdateUserId, userPo.getUserId());
//        // 匹配
//        annexPreLambdaUpdateWrapper.in(AnnexPreEntity::getId, idSet)
//                .eq(AnnexPreEntity::getStatus, CommonEnum.ZERO.getValue());
//        // 更新
//        count = baseMapper.update(null, annexPreLambdaUpdateWrapper);
//        log.info("停用正在`启用`中的前置完成。count={}", count);
    }

    @Override
    public void deleteAnnexPre(List<Long> idList) {
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<AnnexPreEntity> annexPreLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        annexPreLambdaUpdateWrapper.set(AnnexPreEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(AnnexPreEntity::getUpdateTime, date)
                .set(AnnexPreEntity::getUpdateUser, userPo.getUsername())
                .set(AnnexPreEntity::getUpdateUserId, userPo.getUserId());
        // 匹配
        annexPreLambdaUpdateWrapper.in(AnnexPreEntity::getId, idList)
                .eq(AnnexPreEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 更新
        int count = baseMapper.update(null, annexPreLambdaUpdateWrapper);
        log.info("删除附件动态配置前置完成。count={}", count);
    }

    /**
     * 构造附件动态配置前置对象
     * @param annexPreVo 参数对象
     * @return 附件动态配置前置对象
     */
    private AnnexPreEntity buildAnnexPreEntity(AnnexPreVo annexPreVo, AnnexPreEntity annexPre) {
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();
        boolean isSave = Objects.isNull(annexPre);

        if (isSave) {
            annexPre = new AnnexPreEntity();
        }
        annexPre.setClassify(annexPreVo.getClassify())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue());
        if (isSave) {
            annexPre.setId(annexPreVo.getId())
                    .setVersion(this.getNextVersion(annexPreVo.getClassify()))
                    .setStatus(CommonEnum.ONE.getValue())
                    .setDeleteStatus(CommonEnum.ZERO.getValue())
                    .setCreateTime(date)
                    .setCreateUser(userPo.getUsername())
                    .setCreateUserId(userPo.getUserId());
        } else {
            annexPre.setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());
        }
        return annexPre;
    }

    /**
     * 获取下一个版本号
     * @param classify 分类
     * @return 版本号
     */
    private Integer getNextVersion(Integer classify) {
        RLock lock = redissonClient.getLock(RedisConstant.LOCK + EntityConstant.ANNEX + classify);
        // 加锁
        lock.lock();
        try {
            // 获取最大版本号
            Integer maxVersion = baseMapper.selectMaxVersion(classify, CommonEnum.ZERO.getValue());
            if (Objects.isNull(maxVersion)) {
                maxVersion = 0;
            }
            maxVersion += 1;

            return maxVersion;
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }
}